﻿Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.ComponentModel.Design.Serialization
Imports System.Drawing
Imports System.Drawing.Drawing2D
Imports System.Workflow.ComponentModel.Design
Imports System.Workflow.ComponentModel.Serialization

Namespace System.Workflow.Activities
    <DesignerSerializer(GetType(StateDesignerConnectorLayoutSerializer), GetType(WorkflowMarkupSerializer))> _
    Friend Class StateDesignerConnector
        Inherits Connector
        ' Methods
        Friend Sub New(ByVal source As ConnectionPoint, ByVal target As ConnectionPoint)
            MyBase.New(source, target)
        End Sub

        Friend Sub ClearConnectorSegments()
            MyBase.SetConnectorSegments(New Collection([Of] Point))
        End Sub

        Public Overrides Function HitTest(ByVal point As Point) As Boolean
            If ((Not Me.RootStateDesigner Is Nothing) AndAlso (Not Me.RootStateDesigner.ActiveDesigner Is Nothing)) Then
                Return False
            End If
            Return MyBase.HitTest(point)
        End Function

        Protected Overrides Sub OnLayout(ByVal e As ActivityDesignerLayoutEventArgs)
            If Not Me.RootStateDesigner.HasActiveDesigner Then
                MyBase.OnLayout(e)
            End If
        End Sub

        Protected Overrides Sub OnPaint(ByVal e As ActivityDesignerPaintEventArgs)
            If ((Me.RootStateDesigner Is Nothing) OrElse (Me.RootStateDesigner.ActiveDesigner Is Nothing)) Then
                Dim designerTheme As StateMachineTheme = [TryCast](e.DesignerTheme,StateMachineTheme)
                If (Not designerTheme Is Nothing) Then
                    Dim connectorCapSize As New Size((designerTheme.ConnectorSize.Width / 5), (designerTheme.ConnectorSize.Height / 5))
                    Dim connectorSize As Size = designerTheme.ConnectorSize
                    StateMachineDesignerPaint.DrawConnector(e.Graphics, designerTheme.ConnectorPen, New List([Of] Point)(Me.ConnectorSegments).ToArray, connectorCapSize, connectorSize, designerTheme.ConnectorStartCap, designerTheme.ConnectorEndCap)
                End If
            End If
        End Sub

        Protected Overrides Sub OnPaintEdited(ByVal e As ActivityDesignerPaintEventArgs, ByVal segments As Point(), ByVal segmentEditPoints As Point())
            If (((Me.RootStateDesigner Is Nothing) OrElse (Me.RootStateDesigner.ActiveDesigner Is Nothing)) AndAlso TypeOf e.DesignerTheme Is StateMachineTheme) Then
                [Using] pen As Pen = New Pen(WorkflowTheme.CurrentTheme.AmbientTheme.SelectionForeColor, 1!)
                    pen.DashStyle = DashStyle.Dash
                    e.Graphics.DrawLines(pen, segments)
                    If (Not MyBase.Source Is Nothing) Then
                        MyBase.Source.OnPaint(e, False)
                    End If
                    Dim i As Integer
                    For i = 1 To (segments.Length - 1) - 1
                        Me.PaintEditPoints(e, segments(i), False)
                    Next i
                    Dim j As Integer
                    For j = 0 To segmentEditPoints.Length - 1
                        Me.PaintEditPoints(e, segmentEditPoints(j), True)
                    Next j
                    If (Not MyBase.Target Is Nothing) Then
                        MyBase.Target.OnPaint(e, False)
                    End If
                End [Using]
            End If
        End Sub

        Protected Overrides Sub OnPaintSelected(ByVal e As ActivityDesignerPaintEventArgs, ByVal primarySelection As Boolean, ByVal segmentEditPoints As Point())
            If ((Me.RootStateDesigner Is Nothing) OrElse (Me.RootStateDesigner.ActiveDesigner Is Nothing)) Then
                Dim designerTheme As StateMachineTheme = [TryCast](e.DesignerTheme,StateMachineTheme)
                If (Not designerTheme Is Nothing) Then
                    Dim connectorCapSize As New Size((designerTheme.ConnectorSize.Width / 5), (designerTheme.ConnectorSize.Height / 5))
                    Dim connectorSize As Size = designerTheme.ConnectorSize
                    [Using] pen As Pen = New Pen(WorkflowTheme.CurrentTheme.AmbientTheme.SelectionForeColor, 1!)
                        StateMachineDesignerPaint.DrawConnector(e.Graphics, pen, New List([Of] Point)(Me.ConnectorSegments).ToArray, connectorCapSize, connectorSize, designerTheme.ConnectorStartCap, designerTheme.ConnectorEndCap)
                    End [Using]
                    If (Not MyBase.Source Is Nothing) Then
                        MyBase.Source.OnPaint(e, False)
                    End If
                    Dim connectorSegments As ReadOnlyCollection([Of] Point) = Me.ConnectorSegments
                    Dim i As Integer
                    For i = 1 To (connectorSegments.Count - 1) - 1
                        Me.PaintEditPoints(e, connectorSegments.Item(i), False)
                    Next i
                    Dim j As Integer
                    For j = 0 To segmentEditPoints.Length - 1
                        Me.PaintEditPoints(e, segmentEditPoints(j), True)
                    Next j
                    If (Not MyBase.Target Is Nothing) Then
                        MyBase.Target.OnPaint(e, False)
                    End If
                End If
            End If
        End Sub

        Private Sub PaintEditPoints(ByVal e As ActivityDesignerPaintEventArgs, ByVal point As Point, ByVal drawMidSegmentEditPoint As Boolean)
            Dim size As Size = If((Not MyBase.Source Is Nothing), MyBase.Source.Bounds.Size, Size.Empty)
            If Not size.IsEmpty Then
                Dim rect As New Rectangle((point.X - (size.Width / 2)), (point.Y - (size.Height / 2)), size.Width, size.Height)
                If drawMidSegmentEditPoint Then
                    [Using] path As GraphicsPath = New GraphicsPath
                        path.AddLine(New Point((rect.Left + (rect.Width / 2)), rect.Top), New Point(rect.Right, (rect.Top + (rect.Height / 2))))
                        path.AddLine(New Point(rect.Right, (rect.Top + (rect.Height / 2))), New Point((rect.Left + (rect.Width / 2)), rect.Bottom))
                        path.AddLine(New Point((rect.Left + (rect.Width / 2)), rect.Bottom), New Point(rect.Left, (rect.Top + (rect.Height / 2))))
                        path.AddLine(New Point(rect.Left, (rect.Top + (rect.Height / 2))), New Point((rect.Left + (rect.Width / 2)), rect.Top))
                        e.Graphics.FillPath(Brushes.White, path)
                        e.Graphics.DrawPath(e.AmbientTheme.SelectionForegroundPen, path)
                        Return
                    End [Using]
                End If
                rect.Inflate(-1, -1)
                e.Graphics.FillEllipse(e.AmbientTheme.SelectionForegroundBrush, rect)
            End If
        End Sub


        ' Properties
        Friend Property EventHandlerName As String
            Get
                Return Me._eventHandlerName
            End Get
            Set(ByVal value As String)
                Me._eventHandlerName = value
            End Set
        End Property

        Protected Overrides ReadOnly Property ExcludedRoutingRectangles As ICollection([Of] Rectangle)
            Get
                Dim associatedDesigner As StateDesigner = DirectCast(MyBase.Source.AssociatedDesigner, StateDesigner)
                Dim list As New List([Of] Rectangle)(MyBase.ExcludedRoutingRectangles)
                If associatedDesigner.IsRootDesigner Then
                    list.AddRange(associatedDesigner.EventHandlersBounds)
                End If
                Return list.AsReadOnly
            End Get
        End Property

        Private ReadOnly Property RootStateDesigner As StateDesigner
            Get
                Dim parentDesigner As StateDesigner = DirectCast(MyBase.ParentDesigner, StateDesigner)
                Do While (Not parentDesigner Is Nothing)
                    Dim designer2 As StateDesigner = [TryCast](parentDesigner.ParentDesigner,StateDesigner)
                    If (designer2 Is Nothing) Then
                        Return parentDesigner
                    End If
                    parentDesigner = designer2
                Loop
                Return parentDesigner
            End Get
        End Property

        Friend Property SetStateName As String
            Get
                Return Me._setStateName
            End Get
            Set(ByVal value As String)
                Me._setStateName = value
            End Set
        End Property

        Friend Property SourceStateName As String
            Get
                Return Me._sourceStateName
            End Get
            Set(ByVal value As String)
                Me._sourceStateName = value
            End Set
        End Property

        Friend Property TargetStateName As String
            Get
                Return Me._targetStateName
            End Get
            Set(ByVal value As String)
                Me._targetStateName = value
            End Set
        End Property


        ' Fields
        Private _eventHandlerName As String
        Private _setStateName As String
        Private _sourceStateName As String
        Private _targetStateName As String
        Friend Const ConnectorPadding As Integer = 10
    End Class
End Namespace

